﻿#ifndef RXASPECT_H
#define RXASPECT_H

#include <metainfo.h>

#include <threadpool.h>
#include <threadsafe.h>
#include <RXEntitySystem_global.h>

#include "RXECSDef.h"

class RXAspectEngine;
class RXShadowNode;
class RXAspect;

//RXAspectService是一个切面服务提供出来供其它切面访问的服务。注意，它需要保证线程安全
class RXAspectService:public std::enable_shared_from_this<RXAspectService>
{
public:
	virtual ~RXAspectService() {};
};
typedef std::shared_ptr<RXAspectService> RXAspectServicePtr;

//ShadowNodeFactory是用于在前端节点和后端节点之间建立联系的工厂类。当前端节点被创建并被注册后，相应的后端节点也会被创造
class RXEntitySystem_EXPORT ShadowNodeFactoryBase {
public:
	virtual ~ShadowNodeFactoryBase();
	virtual RXShadowNode* CreateNode() = 0;//创建后端节点
	RXShadowNode* GetNode(RXECSDef::NodeId id);//获取后端节点
	void Foreach(const std::function<bool(RXShadowNode*)>& pred);
	int GetSize()const;
protected:
	void ReleaseNode(RXECSDef::NodeId id);//释放节点
	void RegisterNode(RXShadowNode* node);
private:
	std::unordered_map<RXECSDef::NodeId, RXShadowNode*> m_nodeMap;
	friend class RXAspect;
};

typedef std::shared_ptr<ShadowNodeFactoryBase> ShadowNodeFactoryPtr;

//切面的元信息
//name 该切面自身的名称
//rely该切面所依赖的其它切面,该依赖关系会影响各个Aspect的初始化，任务构造，任务执行的顺序
class RXEntitySystem_EXPORT RXAspectInfo {
public:
	RXAspectInfo();
	RXAspectInfo(RXECSDef::RXAspectID name,const std::vector<RXECSDef::RXAspectID>& rely);

	const RXECSDef::RXAspectID& GetName() const;
	const std::vector<RXECSDef::RXAspectID>& GetRelyAspects() const;

private:
	RXECSDef::RXAspectID Name;
	std::vector<RXECSDef::RXAspectID> RelyAspect;
};

class RXEntitySystem_EXPORT RXAspect
{
private:
	struct NodeFactoryInfo {
		ShadowNodeFactoryPtr factory;
		MetaInfo meta;
	};

public:
	RXAspect();

	void SetAspectInfo(const RXAspectInfo& info);//每个Aspect都必须在构造函数内调用，用于告诉引擎自身的名称以及依赖

	const RXAspectInfo& GetAspectInfo() const;

	virtual void AspectBegin() = 0;//Aspect启动时调用，在这里可以使用注册服务，获取服务以及注册后端节点工厂

	template<typename T>
	void RegisterShadowFactory(ShadowNodeFactoryBase* factory) {
		RegisterShadowFactoryImp(T::staticMetaInfo(), factory);
	}

	void PostToFrontNode(RXECSDef::NodeId nodeId, ThreadSafe::Event* event);//向前端节点发送事件

	void RegisterAspectService(const RXECSDef::RXAspectServiceID& name,RXAspectService* service);//注册切面服务
	void UnRegisterAspectService(const RXECSDef::RXAspectServiceID& name);//注销切面服务
	RXAspectService* AcquireAspectService(const RXECSDef::RXAspectServiceID& name);//从整个引擎内搜索指定的服务,该函数只能在Shadow线程中使用
protected:
	virtual void OnNewNodeSpawned(RXECSDef::NodeCreationInfoPtr ret);
	virtual void OnNodeDestoried(RXECSDef::NodeId id);
	virtual RXECSDef::AspectJobList CreateAspectJob(std::chrono::system_clock::duration delta) = 0;//每帧调用，创建切面任务
	void RegisterNodeClass(const MetaInfo& m);//向引擎中注册节点类，使其能够被反射生成
	template <typename T>
	void RegisterNodeClass()
	{
		static_assert(std::is_base_of<RXNode, T>::value,"This Method Is Only For RXNode");
		RegisterNodeClass(T::staticMetaInfo());
	}
private:
	void HandleNodeSpawnEvent(RXECSDef::NodeCreationInfoPtr ret);
	void HandleNodePropertyChangeEvent(RXECSDef::NodePropertyChangeEventPtr ret);
	void HandleNodeDestoryEvent(RXECSDef::NodeId ret);
	void HandleNodePostEvent(RXECSDef::NodeId id,ThreadSafe::Event* e);

	void RegisterShadowFactoryImp(const MetaInfo& meta, ShadowNodeFactoryBase* factory);

private:
	std::vector<NodeFactoryInfo> m_factorys;
	std::map<std::string, std::shared_ptr<RXAspectService>> m_services;
	RXAspectInfo info;
	RXAspectEngine* engine;
	friend class RXAspectEngine;
};


#endif // !RXASPECT_H
